home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1_3 / sys / amiga / splitter / splitter.c < prev   
Encoding:
C/C++ Source or Header  |  1993-03-14  |  15.0 KB  |  735 lines

  1. /*    SCCS Id: @(#)splitter.c        3.1   93/01/08
  2. /*    Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1992, 1993 */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #define SOUT    /* split output files */
  6. #define SPLITSIZE (800 * 1024)        /* somewhat < one floppy */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <fcntl.h>
  12.  
  13. #include <proto/exec.h>
  14. #include <exec/types.h>
  15. #include <exec/nodes.h>
  16. #include <exec/lists.h>
  17.  
  18. #include "split.h"
  19. #include "amiout.h"
  20. #include "arg.h"
  21.  
  22. int main(int,char **);
  23.  
  24. char *code_proto="%n.c%C";
  25. char *data_proto="%n.d%D";
  26. char *dir_proto="%n.dir";
  27.  
  28. char trace[MAXTRACEVAR];        /* debugging info */
  29. char *basename;
  30. int datacount;    /* for ssubst - should be replaced */
  31. int codecount;
  32. int data_file_count=0;    /* actual maxima */
  33. int code_file_count=0;
  34. struct hheader hheader;
  35. struct shunk (*hlist)[];
  36. char buf[80];
  37. int wsf_count;
  38.  
  39. main(argc,argv)
  40.     int argc;
  41.     char **argv;
  42. {
  43.     int cur_arg;
  44.  
  45.     arg_init("C:D:d:t:T",argc,argv);
  46.     while((cur_arg=arg_next())!=ARG_DONE){
  47.     switch(cur_arg){
  48.     case 'C':    /* code prototype */
  49.         code_proto=strdup(argarg);break;
  50.     case 'D':    /* data prototype */
  51.         data_proto=strdup(argarg);break;
  52.     case 'd':    /* directions prototype */
  53.         dir_proto=strdup(argarg);break;
  54.     case 't':    /* trace (debug) */
  55.         {
  56.         int dtype=0,dlevel=0;    /* rude defaults */
  57.         sscanf(argarg,"%d=%d",&dtype,&dlevel);
  58.         if(dtype<0 || dtype>=MAXTRACEVAR){
  59.             fprintf(stderr,"-t: bad trace num ignored\n");
  60.         }else{
  61.             trace[dtype]=dlevel?dlevel:1;
  62.         }
  63.         break;
  64.         }
  65.     case 'T':    /* trace everything */
  66.         {
  67.         int dtype;
  68.         for(dtype=0;dtype<MAXTRACEVAR;dtype++)trace[dtype]=255;
  69.         }
  70.         break;
  71.     default:
  72.         fprintf(stderr,"Unrecognized option.\n");
  73.         /* FALLTHROUGH */
  74.     case ARG_ERROR:
  75.         panic("Error processing arguments.");
  76.     case ARG_FREE:
  77.         basename=strdup(argarg);
  78.         read_load_file(basename);break;
  79.     }
  80.     }
  81.     renumber();
  82.     out_start(code_proto);
  83.     write_header();
  84.     write_code_file();
  85.     out_stop();
  86.     out_start(data_proto);
  87.     write_data_file();
  88.     out_stop();
  89.     write_dir_file();
  90.     exit(0);
  91. }
  92.  
  93. char *
  94. ssubst(buf,pat)
  95.     char *buf;
  96.     const char *pat;
  97. {
  98.     char *buf1=buf;
  99.  
  100.     while(*pat){
  101.     if(*pat!='%'){
  102.         *buf++=*pat++;
  103.     } else {
  104.         pat++;
  105.         switch(*pat++){
  106.         case '%': *buf++='%';break;
  107.         case 'n': strcpy(buf,basename);buf=eos(buf);break;
  108.         case 'D': sprintf(buf,"%02d",datacount);buf=eos(buf);break;
  109.         case 'C': sprintf(buf,"%02d",codecount);buf=eos(buf);break;
  110.         default:  panic("pattern substitution error");
  111.         }
  112.     }
  113.     }
  114.     *buf='\0';
  115.     return buf1;
  116. }
  117.  
  118. void
  119. panic(s)
  120.     char *s;
  121. {
  122.     fprintf(stderr,"\npanic: %s\n",s);
  123.     exit(1);
  124. }
  125.  
  126. char *
  127. eos(s)
  128.     char *s;
  129. {
  130.     while(*s)s++;
  131.     return s;
  132. }
  133.  
  134. /* input routines */
  135.  
  136.     /* macro for reading the next long.  If e==EOF_OK, caller MUST check
  137.      * for EOF condition via hreadval or assure it can't occur */
  138. static int hreadval=0;        /* macro internal temporary */
  139. #define EOF_OK    1
  140. #define EOF_BAD    0
  141. #define READLONG(e)    \
  142.     ((4!=(hreadval=read(f->fd,&(READLONGx),4)))        \
  143.     ?((0==hreadval && (e)                    \
  144.         ?0                        \
  145.         :rderror()))                    \
  146.     :READLONGx)
  147. static long READLONGx;
  148. #define READSHORT(e)    \
  149.     ((2!=(hreadval=read(f->fd,&(READSHORTx),2)))        \
  150.     ?((0==hreadval && (e)                    \
  151.         ?0                        \
  152.         :rderror()))                    \
  153.     :READSHORTx)
  154. static short READSHORTx;
  155.  
  156. #define LONGLEN(x)    (strlen(x)+3 >>2)    /* # longs for a string */
  157.  
  158. void
  159. read_load_file(name)
  160.     char *name;
  161. {
  162.     int t;
  163.     int hc;
  164.     file *f=NewFile(name);
  165.  
  166.         /* read HUNK_HEADER */
  167.     t=READLONG(EOF_BAD);if(t!=HUNK_HEADER)panic("no HUNK_HEADER");
  168.     t=READLONG(EOF_BAD);if(t)while(t--)READLONG(EOF_BAD); /* eat any name */
  169.     hheader.hcount=READLONG(EOF_BAD);
  170.     hheader.first=READLONG(EOF_BAD);
  171.     hheader.last=READLONG(EOF_BAD);
  172.     if(hheader.hcount !=(hheader.last-hheader.first+1))panic("can't count");
  173.     hheader.sizes=calloc(hheader.hcount,sizeof(int*));
  174.     for(t=0;t<hheader.hcount;t++)
  175.     (*hheader.sizes)[t]=READLONG(EOF_BAD);
  176.  
  177.     hlist=calloc(hheader.hcount,sizeof(struct shunk));
  178.     for(hc=0;hc<hheader.hcount;hc++){
  179.     struct shunk *th = &(*hlist)[hc];
  180.             /* read each hunk */
  181.     th->h=ReadHunk(f);
  182.     }
  183.     close(f->fd);
  184. }
  185.  
  186. /* write routines */
  187. #define S_CODE    0
  188. #define S_DATA    1
  189.  
  190. void
  191. write_header(){
  192.     int x;
  193.     int target=0;
  194.  
  195.     owrite_long(HUNK_HEADER);
  196.     owrite_long(0);
  197.     owrite_long(hheader.hcount);
  198.     owrite_long(hheader.first);
  199.     owrite_long(hheader.last);
  200.  
  201.     for(x=0;x<hheader.hcount;x++){
  202.     hunk *hp = (*hlist)[x].h;
  203.     if(hp->hunknum==target){
  204.         owrite_long((*hheader.sizes)[x]);
  205.         target++;
  206.     }
  207.     }
  208.     for(x=0;x<hheader.hcount;x++){
  209.     hunk *hp = (*hlist)[x].h;
  210.     if(hp->hunknum==target){
  211.         owrite_long((*hheader.sizes)[x]);
  212.         target++;
  213.     }
  214.     }
  215.     if(target!=hheader.hcount)panic("lost hunks?");
  216. }
  217.  
  218. void
  219. write_code_file(){
  220.     code_file_count=write_split_file(S_CODE)-1;
  221. }
  222.  
  223. void
  224. write_data_file(){
  225.     data_file_count=write_split_file(S_DATA)-1;
  226. }
  227.  
  228. void
  229. write_dir_file(){
  230.     int x;
  231.     FILE *fp=fopen(ssubst(buf,dir_proto),"w");
  232.  
  233.     fprintf(fp,"# split binary direction file\n");
  234.     fprintf(fp,"# Each line consists of:\n");
  235.     fprintf(fp,"#   A single C or D for the type of the file (Code or Data)\n");
  236.     fprintf(fp,"#   The full path of the file.\n");
  237.  
  238.     for(x=0;x<=code_file_count;x++){
  239.     codecount=x;
  240.     fprintf(fp,"C%s\n",ssubst(buf,code_proto));
  241.     }
  242.     for(x=0;x<=data_file_count;x++){
  243.     datacount=x;
  244.     fprintf(fp,"D%s\n",ssubst(buf,data_proto));
  245.     }
  246.     fclose(fp);
  247. }
  248.  
  249. /* BUGFIX: 9/23/92: see HT() above */
  250. #define HT(x)    ((x) & ~MEM_OBJ_EXTEND)
  251.  
  252. int
  253. write_split_file(fl)
  254.     int fl;
  255. {
  256.     int hc;
  257.     for(hc=0;hc<hheader.hcount;hc++){
  258.     hunk *hp = (*hlist)[hc].h;
  259.     if(fl==S_CODE && HT(hp->rb->id)==HUNK_CODE){
  260.         wsf_hunk(hp);
  261.     } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_DATA){
  262.         wsf_hunk(hp);
  263.     } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_BSS){
  264.         wsf_hunk(hp);
  265.     }
  266.     }
  267.     return wsf_count;
  268. }
  269.  
  270. /* BUGFIX: 9/23/92: see HT() below */
  271. void
  272. wsf_hunk(hp)
  273.     hunk *hp;
  274. {
  275.     listlist *el;
  276.  
  277.     switch(HT(hp->rb->id)){
  278.     case HUNK_CODE:
  279.     case HUNK_DATA:
  280.     owrite(hp->rb->b,(2+hp->rb->b[1])*sizeof(long));
  281.     break;
  282.     case HUNK_BSS:
  283.     owrite(hp->rb->b,2*sizeof(long));
  284.     break;
  285.     default:panic("wsf_hunk: bad type");
  286.     }
  287.     foreach(el,&(hp->reloc),(listlist*)){
  288.     write_lreloc(hp,el);
  289.     }
  290.     owrite_long(HUNK_END);
  291. }
  292.  
  293. void
  294. write_lreloc(hp,ll)
  295.     hunk *hp;listlist *ll;
  296.     {
  297.     block *bp;
  298.  
  299. #ifdef EMIT_32s
  300.     int x;
  301.     ULONG *p;
  302.  
  303.         /* can we write the entire block with a HUNK_RELOC32s? */
  304.     foreach(bp,&(ll->list),(block*)){
  305.     if((((*hlist)[bp->b[1]]).h->hunknum)>0xffff)goto no_32s; /* no */
  306.     for(p= &(bp->b[2]), x=bp->b[0];x;x--,p++){
  307.             if(*p>0xffff)goto no_32s;    /* no, offset too big */
  308.     }
  309.     }
  310.         /* yes */
  311.     owrite_long(HUNK_RELOC32s);
  312.     foreach(bp,&(ll->list),(block*)){
  313.     owrite_long(bp->b[0]);
  314.     owrite_short(((*hlist)[bp->b[1]]).h->hunknum);
  315.     for(p= &(bp->b[2]), x=bp->b[0];x;x--,p++){
  316.         owrite_short(*p);
  317.     }
  318.             /* force long alignment.  Not documented, but makes
  319.              * reading dumps easier */
  320.     if((bp->b[0] & 1) == 0){    /* note hunknum also short */
  321.         owrite_short(0);
  322.     }
  323.     }
  324.     owrite_long(0);
  325.     return;
  326. no_32s:
  327. #endif
  328.     owrite_long(HUNK_RELOC32);
  329.     foreach(bp,&(ll->list),(block*)){
  330.     owrite_long(bp->b[0]);
  331.     owrite_long(((*hlist)[bp->b[1]]).h->hunknum);
  332.     owrite(&(bp->b[2]),bp->b[0]*sizeof(long));
  333.     }
  334.     owrite_long(0);
  335. }
  336.  
  337. void
  338. renumber()
  339. {
  340.     int n;
  341.     n=renumber2(S_CODE,0);
  342.     renumber2(S_DATA,n);
  343. }
  344.  
  345. /* BUGFIX 9/23/92: hp->rb->id must be wrapped with a bit stripper to ignore
  346.  * memory type bits still in that longword.
  347.  */
  348.  
  349. renumber2(fl,n)
  350.     int fl;
  351.     int n;
  352. {
  353.     int hc;
  354.     for(hc=0;hc<hheader.hcount;hc++){
  355.     hunk *hp = (*hlist)[hc].h;
  356.     if(fl==S_CODE && HT(hp->rb->id)==HUNK_CODE){
  357.         hp->hunknum=n++;
  358.     } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_DATA){
  359.         hp->hunknum=n++;
  360.     } else if(fl==S_DATA && HT(hp->rb->id)==HUNK_BSS){
  361.         hp->hunknum=n++;
  362.     }
  363.     }
  364.     return n;
  365. }
  366.  
  367. /* output package */
  368. #ifndef SOUT
  369. /* NB - this version does NOT cope with multiple output files per type */
  370. int ofile;
  371.  
  372. void
  373. out_start(prot)
  374.     char *prot;
  375. {
  376.     datacount=codecount=0;
  377.     file=open(ssubst(buf,prot),O_WRONLY|O_CREAT|O_TRUNC);
  378.     if(ofile<0)panic("can't open output file");
  379. }
  380.  
  381. void
  382. out_stop(){
  383.     close(ofile);
  384. }
  385.  
  386. void
  387. owrite_long(literal)
  388.     long literal;
  389. {
  390.     long x=literal;
  391.     owrite(&x,sizeof(x));
  392. }
  393.  
  394. void
  395. owrite_short(literal)
  396.     short literal;
  397. {
  398.     short x=literal;
  399.     owrite(&x,sizeof(x));
  400. }
  401.  
  402. void
  403. owrite(where,len)
  404.     void *where;
  405.     long len;
  406. {
  407.     write(ofile,where,len);
  408. }
  409. #else /* SOUT */
  410. int ofile=0;
  411. int osize;
  412. char *oprot;
  413. void
  414. out_start(prot)
  415.     char *prot;
  416. {
  417.     datacount=codecount=wsf_count=0;
  418.     oprot=prot;
  419.     new_file();
  420. }
  421.  
  422. void
  423. out_stop(){
  424.     close(ofile);
  425.     ofile=0;
  426. }
  427.  
  428. void
  429. owrite_long(literal)
  430.     long literal;
  431. {
  432.     long x=literal;
  433.     if((osize+sizeof(x))>SPLITSIZE)new_file();
  434.     owrite(&x,sizeof(x));
  435.     osize += sizeof(x);
  436. }
  437.  
  438. void
  439. owrite_short(literal)
  440.     short literal;
  441. {
  442.     short x=literal;
  443.     if((osize+sizeof(x))>SPLITSIZE)new_file();
  444.     owrite(&x,sizeof(x));
  445.     osize += sizeof(x);
  446. }
  447.  
  448. void
  449. owrite(where,len)
  450.     void *where;
  451.     long len;
  452. {
  453.     if((osize+len)>SPLITSIZE)new_file();
  454.     write(ofile,where,len);
  455.     osize += len;
  456. }
  457.  
  458. void
  459. new_file(){
  460.     if(ofile)close(ofile);
  461.     ofile=open(ssubst(buf,oprot),O_WRONLY|O_CREAT|O_TRUNC);
  462.     if(ofile<0)panic("can't open output file");
  463.     wsf_count++,datacount++,codecount++;
  464.     osize=0;
  465. }
  466. #endif /* SOUT */
  467.  
  468. struct Node *Head(l)
  469.     struct List *l;
  470. {
  471.     if(!l)panic("Head(NULL)\n");
  472.     return l->lh_Head->ln_Succ?l->lh_Head:0;
  473. }
  474. struct Node *Tail(l)
  475.     struct List *l;
  476. {
  477.     if(!l)panic("Tail(NULL)\n");
  478.     return (l->lh_TailPred==(NODE_P)l)?0:l->lh_TailPred;
  479. }
  480. struct Node *Next(n)
  481.     struct Node *n;
  482. {
  483.     if(!n)printf("Warning: Next(NULL)\n");
  484.     return n?(n->ln_Succ->ln_Succ?n->ln_Succ:0):0;
  485. }
  486. struct Node *Prev(n)
  487.     struct Node *n;
  488. {
  489.     if(!n)printf("Warning: Prev(NULL)\n");
  490.     return n?(n->ln_Pred->ln_Pred?n->ln_Pred:0):0;
  491. }
  492.  
  493. struct List *_fortemp;    /* scratch for foreach macro */
  494.  
  495. void
  496. dump_after_read(struct List *root){
  497.     file *f;
  498.     foreach(f,root,(file *)){
  499.         punit *p;
  500.         printf("FILE '%s'\n",f->name);
  501.         foreach(p,&(f->punits),(punit *)){
  502.         hunk *h;
  503.         print_text_block("\tPUNIT %.*s\n",p->unit_header);
  504.         if(p->libsize){
  505.         printf("\tlibsize=%08x\n",p->libsize);
  506.         } else {
  507.         /* */
  508.         }
  509.         foreach(h,&(p->hunks),(hunk *)){
  510.         print_text_block("\t\tHUNK %.*s",h->name);
  511.         printf(" @%08x\n",h);
  512.         print_bin_block(h->rb);
  513.         printf("\t\t\tCode Reloc\n");
  514.         printf("\t\t\tData Reloc\n");
  515.         if(h->merge)printf("\t\t\tmerge(%08x)\n",h->merge);
  516.         if(h->hunkstart)printf("\t\t\thunkstart\n");
  517.         if(h->hunkchain)printf("\t\t\thunkchain\n");
  518.         if(h->hunkgone)printf("\t\t\thunkgone\n");
  519.         printf("\t\t\toverlay(%08x) hunknum(%08x) offset(%08x)\n",
  520.           h->overlay,h->hunknum,h->hunkoffset);
  521.         }
  522.         }
  523.     }
  524. }
  525.  
  526. void
  527. print_text_block(char *fmt,block *b){
  528.     if(!b){
  529.     printf(fmt,10,"(no block)");
  530.     } else {
  531.     if(b->sw){
  532.         printf(fmt,13,"(swapped out)");
  533.     } else {
  534.         if(!(b->b[1]) || !*(char*)&(b->b[2])){
  535.         printf(fmt,6,"(null)");
  536.         } else {
  537.         printf(fmt,b->b[1]*4,&(b->b[2]));
  538.         }
  539.     }
  540.     }
  541. }
  542.  
  543. void
  544. print_bin_block(block *b){
  545.     if(b->sw){
  546.     printf("\t\t\t(swapped out)\n");
  547.     } else {
  548.     printf("\t\t\tid1=%08x id2=%08x len=%08x\n", b->id,b->b[0],b->b[1]);
  549.     }
  550. }
  551.  
  552. /*
  553.  * read routines
  554.  */
  555.  
  556. /*
  557.  * ReadSimpleBlock
  558.  * If the given id is recognized as a simple block (id, length, data),
  559.  * allocate and fill in a block structure.  Include the id in the block.
  560.  */
  561. block *ReadSimpleBlock(f,id)
  562.     file *f;
  563.     long id;
  564. {
  565.     long len;
  566.     long hid;
  567.     block *b;
  568.  
  569.     hid=id & 0x0fffffff;
  570.     if(    hid !=HUNK_UNIT && hid != HUNK_NAME && hid != HUNK_CODE &&
  571.         hid != HUNK_DATA && hid != HUNK_BSS && hid != HUNK_DEBUG
  572.       ){
  573.     printf("%08x\n",id);
  574.     panic("ReadSImpleBlock");
  575.     }
  576.  
  577.     len=READLONG(EOF_BAD);
  578.     b=NewBlock();
  579.     b->id=id;
  580.     b->sw=0;
  581.     b->b=NewData((hid==HUNK_BSS)?2:len+2);
  582.     b->b[0]=id;
  583.     b->b[1]=len;
  584.     if(hid != HUNK_BSS)read(f->fd,&(b->b[2]),len*4);
  585.     return(b);
  586. }
  587.  
  588. /*
  589.  * TossSimpleBlock
  590.  * Skip past something we don't need.
  591.  */
  592. int TossSimpleBlock(f)
  593.     file *f;
  594. {
  595.     long len=READLONG(EOF_BAD);
  596.  
  597.     if(len)if( lseek(f->fd,len*4,1) == -1)panic("Toss failed\n");
  598.     return(len);
  599. }
  600.  
  601. /*
  602.  * ReadHunk
  603.  * Read an entire hunk, building lists of each block type in the given hunk
  604.  * structure.  If we are listing, do the listing as we read so we can see
  605.  * where things die if we hit a type code we don't recognize.
  606.  */
  607. hunk *ReadHunk(f)
  608.     file *f;
  609. {
  610.     long id;
  611.     hunk *h=NewHunk();
  612.  
  613.     while(1){
  614.     id=READLONG(EOF_OK);
  615.     switch(id & 0x0fffffff){    /* ignore memory type bits */
  616.     case 0: return 0;        /* EOF - not good test */
  617.     case HUNK_RELOC32:
  618.         LIST{printf("Reloc32:\n");}
  619.         ReadReloc(f,id,&h->reloc);break;
  620.     case HUNK_CODE:
  621.         h->rb=ReadSimpleBlock(f,id);
  622.         LIST{printf("Code size %d\n",block_size(h->rb)*4);};
  623.         break;
  624.     case HUNK_DATA:
  625.         h->rb=ReadSimpleBlock(f,id);
  626.         LIST{printf("Data size %d\n",block_size(h->rb)*4);};
  627.         break;
  628.     case HUNK_BSS:
  629.         h->rb=ReadSimpleBlock(f,id);
  630.         LIST{printf("Bss size %d\n",block_size(h->rb)*4);};
  631.         break;
  632.     case HUNK_SYMBOL:
  633.         while(TossSimpleBlock(f))READLONG(EOF_BAD);
  634.         LIST{printf("Symbols skipped\n");};
  635.         break;
  636.     case HUNK_DEBUG:
  637.         (void)TossSimpleBlock(f);
  638.         LIST{printf("Debug hunk skipped\n");};
  639.         break;
  640.     case HUNK_END:    LIST{printf("End of hunk\n");};return h;
  641.     case HUNK_BREAK:LIST{printf("End of overlay\n");};break;
  642.     default:
  643.             printf("Lost id=0x%x\n",id);exit(2);
  644.     }
  645.     }
  646.     return 0;
  647. }
  648.  
  649. /*
  650.  * ReadReloc
  651.  * Read a relocation block and build a linked list of the sections.
  652.  * If we are listing, do that now.
  653.  */
  654. void ReadReloc(f,id,ls)
  655.     file *f;
  656.     long id;
  657.     struct List *ls;
  658. {
  659.     long len;
  660.     block *cur;
  661.     listlist *blist=NewListList();
  662.  
  663.     AddTail(ls,blist);
  664.     blist->id=id;
  665.     len=READLONG(EOF_BAD);
  666.     while(len){
  667.     cur=NewBlock();
  668.     cur->b=NewData(len+2);
  669.     read(f->fd,&(cur->b[1]),len*4+4);
  670.     cur->b[0]=len;
  671.     LIST{printf("\thunk #%d - %d items\n",cur->b[1],len);}
  672.     AddTail(&blist->list,cur);
  673.     len=READLONG(EOF_BAD);
  674.     }
  675. }
  676.  
  677. int rderror(){
  678.     panic("read error\n");
  679.     return 0;    /* just to make it quiet - NOTREACHED */
  680. }
  681.  
  682. long block_size(blk)
  683.     block *blk;
  684. {
  685.     return(blk->b[1]);
  686. }
  687.  
  688. /* Allocation routines - if this was C++ then this code would be buried in the
  689.  * constructors.  Doing it this way means we can re-write the allocation later
  690.  * to allocate things we'll need lots of in larger blocks to avoid the time and
  691.  * space penalties of malloc. */
  692. file *NewFile(fname)
  693.     char *fname;
  694.     {
  695.     file *ret=calloc(sizeof(file),1);
  696.  
  697.     NewList(&ret->punits);
  698.     ret->name=strdup(fname);
  699.     ret->fd= open(fname,O_RDONLY);
  700.     return(ret);
  701. }
  702.  
  703. punit *NewPunit(){
  704.     punit *ret=calloc(sizeof(punit),1);
  705.     NewList(&ret->hunks);
  706.     return(ret);
  707. }
  708.  
  709. hunk *NewHunk(){
  710.     hunk *ret=calloc(sizeof(hunk),1);
  711.  
  712.     NewList(&ret->reloc);
  713.     NewList(&ret->dreloc);
  714.     NewList(&ret->extsym);
  715.     ret->overlay=UNASSIGNED_HUNK;
  716.     return(ret);
  717. }
  718.  
  719. block *NewBlock(){
  720.     return calloc(sizeof(block),1);
  721. }
  722.  
  723. listlist *NewListList(){
  724.     listlist *ret=calloc(sizeof(listlist),1);
  725.  
  726.     NewList(&ret->list);
  727.     return(ret);
  728. }
  729.  
  730. long *NewData(longs)
  731.     long longs;    
  732.     {
  733.     return(malloc(longs*4));
  734. }
  735.